home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / text / show / jmore03.lzh / jmoresrc.LZH / jmore.c < prev    next >
C/C++ Source or Header  |  1992-11-05  |  12KB  |  594 lines

  1. /*
  2.  *    jmore.c
  3.  *    H.Ohkubo Oct. 4, 1992
  4.  *
  5.  *    Modified Oct. 17, 1992 (Ver.0.02)
  6.  *    Modified 0ct. 22, 1992 (Ver.0.03)
  7.  */
  8.  
  9. #include    <exec/types.h>
  10. #include    <exec/ports.h>
  11. #include    <intuition/intuitionbase.h>
  12. #include    <graphics/gfxbase.h>
  13. #include    <workbench/startup.h>
  14. #include    <functions.h>
  15. #include    <stdio.h>
  16. #include    <stdlib.h>
  17. #include    <limits.h>
  18. #include    <string.h>
  19. #include    <ctype.h>
  20. #include    "jctype.h"
  21. #include    "openlib.h"
  22. #include    "jFont.h"
  23. #include    "jmore.h"
  24.  
  25. struct    Screen    *Scrn = NULL;
  26. struct    Window    *Wind = NULL;
  27. struct    RastPort    *rport = NULL;
  28. int    current_x, current_y;
  29.  
  30. /* for backcscroll */
  31. USHORT    current_line, top_line;
  32. SHORT    count[USHRT_MAX];
  33.  
  34. FILE    *infile = NULL;
  35. char    in_fname[FNAMELEN];
  36.  
  37. struct    TextFont    *current_font = NULL;
  38. struct    TextFont    *resident_font[KATA + 1];
  39.  
  40. BPTR    olddir = NULL;
  41.  
  42. int    tabspc = TABSPC;
  43. BOOL    regular = FALSE;
  44.  
  45. struct    MsgPort    *jMorePort = NULL;
  46. struct    jFontMsg    fontMsg;
  47.  
  48. /* prototypes */
  49. VOID    print_file(VOID);
  50. int    print_file_doit(VOID);
  51. VOID    handle_ank_code(char *);
  52. VOID    handle_kanji_code(char *);
  53. VOID    handle_ctrl_code(int);
  54. char    *strchr_r(char *, int);
  55. int    keyin_loop(LONG *, int, char *);
  56. int    print_message(char *);
  57. int    handle_rawkey(VOID);
  58. int    count_bytes(LONG *, int);
  59. VOID    fseek_back(int);
  60. VOID    init_myMsg(VOID);
  61. struct    MsgPort    *init_myport(VOID);
  62. struct    TextFont    *get_font(USHORT);
  63. struct    TextFont    *init_resident_font(VOID);
  64. VOID    OpenScrnWind(VOID);
  65. FILE    *fset(char *, char *);
  66. VOID    clean_exit(char *, int);
  67. VOID    usage(VOID);
  68. VOID    get_startup(VOID);
  69. int    set_startup_value(FILE *);
  70. char    *my_getline(FILE *);
  71.  
  72.  
  73. VOID    main(int argc, char *argv[])
  74. {
  75.     if (argc == 0) {
  76.         struct    WBStartup    *argmsg = (struct WBStartup *)argv;
  77.         struct    WBArg    *wb_arg = argmsg->sm_ArgList;
  78.  
  79.         if (argmsg->sm_NumArgs < 2)
  80.             exit(EXIT_FAILURE);
  81.         if (wb_arg[1].wa_Lock != NULL)
  82.             olddir = CurrentDir(wb_arg[1].wa_Lock);
  83.         strcpy(in_fname, wb_arg[1].wa_Name);
  84.     }
  85.     else {
  86.         if (argc < 2)
  87.             usage();
  88.         puts(COPYRIGHT);
  89.         strcpy(in_fname, argv[1]);
  90.     }
  91.     infile = (FILE *)fset(in_fname, READ_BINARY);
  92.  
  93.     get_startup();
  94.     init_myMsg();
  95.     if (!OpenLib())
  96.         clean_exit("No Library !", RETURN_FAIL);
  97.     OpenScrnWind();    /* initialize jmore's screen */
  98.  
  99.     print_file();
  100.  
  101.     clean_exit(END_MESSAGE, RETURN_OK);
  102. }
  103.  
  104.  
  105. #define    tabwidth(w)    (tabspc*(w))
  106. #define    tabalign(x, w)    (((x)/tabwidth(w))*tabwidth(w) + tabwidth(w))
  107.  
  108. char    pool[BUFFSIZE + 1];
  109. char    strbuff[STRBUFSIZE];
  110.  
  111. VOID    print_file(VOID)
  112. {
  113.     current_font = init_resident_font();
  114.     SetFont(rport, current_font);
  115.     SetAPen(rport, 1);
  116.     SetDrMd(rport, JAM2);
  117.  
  118.     current_x = Wind->BorderLeft;
  119.     current_y = Wind->BorderTop + rport->TxBaseline;
  120.     Move(rport, current_x, current_y);
  121.  
  122.     current_line = top_line = 0;
  123.     count[current_line] = 0;
  124.  
  125.     while (print_file_doit())
  126.         ;
  127. }
  128.  
  129.  
  130. int    print_file_doit(VOID)
  131. {
  132.     int    len, remaining_size = 0, n;
  133.     char    *buff, *buff_tail, *head, *next_head, *p;
  134. #if    0
  135.     char    *line_head, *line_tail;
  136. #endif
  137.  
  138.     pool[0] = pool[BUFFSIZE] = LF;
  139.     buff = pool + 1;
  140.     buff_tail = pool + BUFFSIZE;
  141.  
  142.     head = buff;
  143.     while ((len = fread(head, sizeof(char), buff_tail - head, infile)) > 0) {
  144.         next_head = strchr_r(head + len - 1, LF) + 1;
  145.         p = buff;
  146.         while (p < next_head) {
  147.             count[current_line]++;
  148.             switch (nthmsctype(buff, p - buff)) {
  149.             case CT_KJ2:
  150.                 handle_kanji_code(p);
  151.                 break;
  152.             case CT_KJ1:
  153.                 break;
  154.             case CT_ANK:
  155.                 handle_ank_code(p);
  156.                 break;
  157.             case CT_ILGL:
  158.             default:
  159.                 handle_ctrl_code((int)(*p));
  160.                 break;
  161.             }
  162.             p++;
  163.             if (current_y > (Wind->Height - FONT_SIZE)) {
  164.                 switch (n = keyin_loop((VOID *)&p, p - buff, MORE_MES)) {
  165.                 case QUIT:
  166.                     return FALSE;
  167.                     break;
  168.                 case NORMAL:
  169.                     break;
  170.                 default:    /* back scroll */
  171.                     fseek_back(len + remaining_size + n);
  172.                     return TRUE;
  173.                     break;
  174.                 }
  175.             }
  176.         }
  177.         remaining_size = len - (next_head - head);
  178.         memmove(buff, next_head, remaining_size);
  179.         head = buff + remaining_size;
  180.     }
  181.     if ((n = keyin_loop((VOID *)&buff, 0, FILE_END_MES)) > 0) {
  182.         fseek_back(len + remaining_size + n);
  183.         return TRUE;
  184.     }
  185.  
  186.     return FALSE;
  187. }
  188.  
  189.  
  190. VOID    handle_ank_code(char *code)
  191. {
  192.     if (current_font != resident_font[ANK]) {
  193.         Text(rport, strbuff, strlen(strbuff));
  194.         strbuff[0] = NUL;
  195.         current_font = resident_font[ANK];
  196.         SetFont(rport, current_font);
  197.         current_x = rport->cp_x;
  198.     }
  199.  
  200.     if ((current_x += current_font->tf_XSize) >= Wind->Width)
  201.         handle_ctrl_code(LF);
  202.     strncat(strbuff, code, sizeof(char));
  203. }
  204.  
  205.  
  206. VOID    handle_kanji_code(char *p)
  207. {
  208.     USHORT    kanji;
  209.     int    fontnum;
  210.     char    code;
  211.     struct    TextFont    *tf;
  212.  
  213.     kanji = (*(p - 1)&0xff)<<CHAR_BIT | *p&0xff;
  214.     kanji = mstojis(kanji);
  215.     fontnum = ((kanji>>CHAR_BIT)&0xff) - SPC;
  216.     code = (char)(kanji&0xff);
  217.  
  218.     if (fontnum >= SYM1 && fontnum <= KATA) {
  219.         if (regular && (isjalnum(kanji) || isjsymbol(kanji))) {
  220.             int    ascii_code;
  221.  
  222.             if ((ascii_code = jistoascii(kanji))) {
  223.                 tf = resident_font[ANK];
  224.                 code = (char)ascii_code;
  225.             }
  226.             else
  227.                 tf = resident_font[fontnum];
  228.         }
  229.         else
  230.             tf = resident_font[fontnum];
  231.     }
  232.     else {
  233.         if ((tf = get_font(kanji)) == NULL) {
  234.             tf = resident_font[SYM1];
  235.             code = KNJ_ILGL;
  236.         }
  237.     }
  238.     if (current_font != tf) {
  239.         Text(rport, strbuff, strlen(strbuff));
  240.         strbuff[0] = NUL;
  241.         current_font  = tf;
  242.         SetFont(rport, current_font);
  243.         current_x = rport->cp_x;
  244.     }
  245.  
  246.     if ((current_x += current_font->tf_XSize) >= Wind->Width)
  247.         handle_ctrl_code(LF);
  248.     strncat(strbuff, &code, sizeof(char));
  249. }
  250.  
  251.  
  252. VOID    handle_ctrl_code(int code)
  253. {
  254.     Text(rport, strbuff, strlen(strbuff));
  255.     strbuff[0] = NUL;
  256.  
  257.     switch (code) {
  258.     case LF:
  259.         current_x = Wind->BorderLeft;
  260.         current_y += FONT_SIZE;
  261.         Move(rport, current_x, current_y);
  262.         count[++current_line] = 0;
  263.         break;
  264.     case TAB:
  265.         current_x = tabalign(rport->cp_x, resident_font[ANK]->tf_XSize);
  266.         Move(rport, current_x, current_y);
  267.         break;
  268.     default:
  269.         break;
  270.     }
  271. }
  272.  
  273.  
  274. char    *strchr_r(char *str, int c)
  275. {
  276.     while (*str != c)
  277.         str--;
  278.  
  279.     return str;
  280. }
  281.  
  282.  
  283. #define    forward_scroll(rport)    (ScrollRaster((rport), 0, FONT_SIZE, \
  284.                 Wind->BorderLeft, Wind->BorderTop, \
  285.                 Wind->Width, Wind->Height - FONT_SIZE - 1))
  286. #define    backward_scroll(rport)    (ScrollRaster((rport), 0, -FONT_SIZE, \
  287.                 Wind->BorderLeft, Wind->BorderTop, \
  288.                 Wind->Width, Wind->Height - FONT_SIZE - 1))
  289. #define    clear_screen(rport)    (SetRast((rport), 0))
  290.  
  291. int    keyin_loop(LONG *point, int nbyte, char *mes)
  292. {
  293.     int    retval = NORMAL;
  294.  
  295.     switch (print_message(mes)) {
  296.     case QUIT_PRG:
  297.         retval = QUIT;
  298.         break;
  299.     case LINE_SCROLL:
  300.         current_y -= FONT_SIZE;
  301.         Move(rport, current_x, current_y);
  302.         forward_scroll(rport);
  303.         top_line++;
  304.         break;
  305.     case BACK_LINE:
  306.         current_y = Wind->BorderTop + rport->TxBaseline;
  307.         Move(rport, current_x, current_y);
  308.         if (top_line > 0) {
  309.             backward_scroll(rport);
  310.             top_line--;
  311.         }
  312.         retval = count_bytes(point, nbyte);
  313.         break;
  314.     case BACK_SCROLL:
  315.         current_y = Wind->BorderTop + rport->TxBaseline;
  316.         Move(rport, current_x, current_y);
  317.         clear_screen(rport);
  318.         top_line =  (top_line > TOTAL_LINES) ?
  319.             top_line - TOTAL_LINES : 0;
  320.         retval = count_bytes(point, nbyte);
  321.         break;
  322.     case PAGE_SCROLL:
  323.     default:
  324.         current_y = Wind->BorderTop + rport->TxBaseline;
  325.         Move(rport, current_x, current_y);
  326.         clear_screen(rport);
  327.         top_line = current_line;
  328.         break;
  329.     }
  330.  
  331.     return    retval;
  332. }
  333.  
  334.  
  335. int    print_message(char *mes)
  336. {
  337.     struct    TextFont    *tf = current_font;
  338.     int    x, y;
  339.     char    strbuf[STRBUFSIZE];
  340.  
  341.     x = Wind->BorderLeft;
  342.     y = Wind->Height - FONT_SIZE + rport->TxBaseline;
  343.     Move(rport, x, y);
  344.  
  345.     current_font = resident_font[ANK];
  346.     SetFont(rport, current_font);
  347.  
  348.     sprintf(strbuf, mes, in_fname);
  349.     SetDrMd(rport, JAM2|INVERSVID);
  350.     Text(rport, strbuf, strlen(strbuf));
  351.     SetDrMd(rport, JAM2);
  352.  
  353.     current_font = tf;
  354.     SetFont(rport, current_font);
  355.  
  356.     return handle_rawkey();
  357. }
  358.  
  359.  
  360. int    handle_rawkey(VOID)
  361. {
  362.     BOOL    done = FALSE;
  363.     int    retval;
  364.     struct    IntuiMessage    *msg;
  365.  
  366.     while (!done) {
  367.         WaitPort(Wind->UserPort);
  368.         while (msg = (struct IntuiMessage *)GetMsg(Wind->UserPort)) {
  369.             ReplyMsg((struct Message *)msg);
  370.             switch (msg->Class) {
  371.             case RAWKEY:
  372.                 switch (msg->Code) {
  373.                 case QUIT_PRG:
  374.                 case LINE_SCROLL:
  375.                 case BACK_LINE:
  376.                 case PAGE_SCROLL:
  377.                 case BACK_SCROLL:
  378.                     retval = msg->Code;
  379.                     done = TRUE;
  380.                 default:
  381.                     break;
  382.                 }
  383.                 break;
  384.             default:
  385.                 break;
  386.             }
  387.         }
  388.     }
  389.  
  390.     return retval;
  391. }
  392.  
  393.  
  394. int    count_bytes(LONG *point, int nbyte)
  395. {
  396.     int    sum = 0;
  397.  
  398.     do {
  399.         sum += count[--current_line];
  400.     } while (current_line != top_line);
  401.  
  402.     count[current_line] = 0;
  403.  
  404.     if (sum > nbyte)
  405.         return sum - nbyte;
  406.     else {
  407.         *point -= sum;
  408.         return NORMAL;
  409.     }
  410. }
  411.  
  412.  
  413. VOID    fseek_back(int nbyte)
  414. {
  415.     if (fseek(infile, -nbyte, SEEK_CUR) != 0)
  416.         clean_exit("fseek error !", RETURN_FAIL);
  417. }
  418.  
  419.  
  420. /* initialize the jFontMsg structure */
  421. VOID    init_myMsg(VOID)
  422. {
  423.     struct    jFontMsg    *msg = &fontMsg;
  424.  
  425.     msg->msg.mn_Node.ln_Type = NT_MESSAGE;
  426.     msg->msg.mn_Length = sizeof(struct jFontMsg);
  427.     msg->msg.mn_ReplyPort = init_myport();
  428. }
  429.  
  430.  
  431. /* initialize the MsgPort for ReplyMsg */
  432. struct    MsgPort    *init_myport(VOID)
  433. {
  434.     if (FindPort(JMOREPORT) == NULL) {
  435.         if ((jMorePort = CreatePort(JMOREPORT, NORMAL_PRI)) != NULL)
  436.             return jMorePort;
  437.     }
  438.     clean_exit("jMore is already used.", RETURN_FAIL);
  439.  
  440.     return (struct MsgPort *)NULL;    /* but not reached here */
  441. }
  442.  
  443.  
  444. struct    TextFont    *get_font(USHORT kanji)
  445. {
  446.     struct    MsgPort    *mPort;
  447.     struct    jFontMsg    *msg = &fontMsg;
  448.  
  449.     msg->kanji = kanji;
  450.     Forbid();
  451.     if ((mPort = FindPort(JFONTPORT)) == NULL)
  452.         clean_exit("jFontSys is not installed !", RETURN_FAIL);
  453.     PutMsg(mPort, (struct Message *)msg);
  454.     Permit();
  455.  
  456.     WaitPort(jMorePort);
  457.     msg = (struct jFontMsg *)GetMsg(jMorePort);
  458.  
  459.     return msg->font;
  460. }
  461.  
  462.  
  463. struct    TextFont    *init_resident_font(VOID)
  464. {
  465.     int    i;
  466.  
  467.     for (i = SYM1; i <= KATA; i++)
  468.         resident_font[i] = get_font((USHORT)((i + ' ')<<CHAR_BIT));
  469.  
  470.     return (resident_font[ANK] = get_font((USHORT)ANK_FONT_CODE));
  471. }
  472.  
  473.  
  474. /* ScrnDefn & WindDefn is declere in jmore.h */
  475. VOID    OpenScrnWind(VOID)
  476. {
  477.     if ((Scrn = (struct Screen *)OpenScreen(&ScrnDefn)) == NULL)
  478.         clean_exit("No Screen !", RETURN_FAIL);
  479.     ShowTitle(Scrn, FALSE);
  480.  
  481.     WindDefn.Screen = Scrn;
  482.     if ((Wind = (struct Window *)OpenWindow(&WindDefn)) == NULL)
  483.         clean_exit("No Window !", RETURN_FAIL);
  484.  
  485.     rport = Wind->RPort;
  486. }
  487.  
  488.  
  489. FILE    *fset(char *fname, char *mode)
  490. {
  491.     FILE    *fp;
  492.  
  493.     if ((fp = fopen(fname, mode)) == NULL)
  494.         clean_exit(strcat(fname, " not open !"), RETURN_FAIL);
  495.  
  496.     return fp;
  497. }
  498.  
  499.  
  500. VOID    clean_exit(char *mes, int extval)
  501. {
  502.     if (Wind)
  503.         CloseWindow(Wind);
  504.     if (Scrn)
  505.         CloseScreen(Scrn);
  506.     CloseLib();
  507.  
  508.     if (jMorePort)
  509.         DeletePort(jMorePort);
  510.  
  511.     if (infile)
  512.         fclose(infile);
  513.  
  514.     if (olddir)
  515.         CurrentDir(olddir);
  516.  
  517.     if (*mes)
  518.         fprintf(stderr, "%s\n", mes);
  519.  
  520.     exit(extval);
  521. }
  522.  
  523.  
  524. VOID    usage(VOID)
  525. {
  526.     puts(ERROR_MESSAGE);
  527.     exit(EXIT_FAILURE);
  528. }
  529.  
  530.  
  531. /* for startup file routine */
  532. VOID    get_startup(VOID)
  533. {
  534.     FILE    *fp;
  535.  
  536.     if ((fp = fopen(STARTUP, READ_BINARY)) != NULL) {
  537.         while (set_startup_value(fp) != EOF)
  538.             ;
  539.         fclose(fp);
  540.     }
  541. }
  542.  
  543.  
  544. int    set_startup_value(FILE *fp)
  545. {
  546.     char    *lp, *name_end, *value_head;
  547.     int    c;
  548.  
  549.     lp = my_getline(fp);
  550.     if ((name_end = strchr(lp, '=')) != NULL) {
  551.         value_head = name_end + 1;
  552.         if (strncmp(startup[TAB_WIDTH], lp, name_end - lp) == 0) {
  553.             tabspc = atoi(value_head);
  554.         }
  555.     }
  556.     else if (strlen(lp) > 0) {
  557.         if (strcmp(startup[REGULAR], lp) == 0) {
  558.             regular = TRUE;
  559.         }
  560.     }
  561.     c = fgetc(fp);
  562.     ungetc(c, fp);    /* for check EOF */
  563.  
  564.     return c;
  565. }
  566.  
  567.  
  568. #define    LINEBUFLEN    80
  569.  
  570. char    *my_getline(FILE *fp)
  571. {
  572.     int    c, iscomment = FALSE;
  573.     static    char    linebuf[LINEBUFLEN], *lp;
  574.  
  575.     lp = linebuf;
  576.     while ((c = fgetc(fp)) != LF && c != EOF) {
  577.         if (!iscomment && isgraph(c)) {
  578.             switch (c) {
  579.             case COMMENT_MARK:
  580.                 iscomment = TRUE;
  581.                 break;
  582.             default:
  583.                 if (islower(c))
  584.                     c = toupper(c);
  585.                 *lp++ = (char)c;
  586.                 break;
  587.             }
  588.         }
  589.     }
  590.     *lp = NUL;
  591.  
  592.     return linebuf;
  593. }
  594.